﻿/**
 * Proto导出工具
 */

using System.IO;
using UnityEditor;
using System.Text.RegularExpressions;
using System.Text;
using Base.Debug;
using System.Collections.Generic;
using Editor.Proto;
using UnityEngine;
using System.Diagnostics;
using Debugger = Base.Debug.Debugger;
using System;
using System.Threading;

public class ProtoEditor
{
    /// <summary>
    /// proto协议存放的路径
    /// </summary>
    private static string PROTOPATH = "Server/proto";
    /// <summary>
    /// Proto转CS的路径
    /// </summary>
    private static string OUTCSPATH = "Assets/HotUpdate/Proto";
    /// <summary>
    /// 自动生成的NetMsg协议号和协议类型映射关系
    /// NetMsgConfig只是用来手动协议号和协议的配置文件
    /// </summary>
    private static string NETMSGCONFIG = "Server/NetMsgConfig.json";
    private static string OUTNETMSGPATH = OUTCSPATH + "/NetMsg.cs";

   

    public static string outputpath = "";
    /// <summary>
    /// Proto -> CS
    /// </summary>
    [MenuItem("Tools/Proto/ExportCS_proto3")]
    public static void ExportCS_proto3()
    {
        outputpath = $"{Application.dataPath.Replace("/", "\\")}\\HotUpdate";
        PROTOPATH = "Server/proto";
        docmd("proto");
        AssetDatabase.Refresh();
        Debugger.Log("Proto ExportCS Done!");
    }

    /// <summary>
    /// Proto -> CS
    /// </summary>
    [MenuItem("Tools/Proto/ExportCS_proto3_client")]
    public static void ExportCS_proto3_client()
    {
        outputpath = $"{Application.dataPath.Replace("/", "\\")}\\HotUpdate\\clientproto";
        PROTOPATH= "Server/Clientproto";
        docmd("Clientproto");
        AssetDatabase.Refresh();
        Debugger.Log("Proto ExportCS Done!");
    }

    /// <summary>
    /// 自动生成NetMsg相关
    /// JsonUtility解析json的时候字段名要一致
    /// </summary>
    [MenuItem("Tools/Proto/ExportCSNetMsg")]
    private static void ExportCSNetMsg()
    {
        outputpath = $"{Application.dataPath.Replace("/", "\\")}\\HotUpdate";
        PROTOPATH= "Server/proto";
        docmd("proto");
        var config = Base.Utils.FileUtil.ReadAllText(NETMSGCONFIG);
        config = "{ \"list\": " + config + "}";
        var netMsg = UnityEngine.JsonUtility.FromJson<NetMsgConfig<Editor.Proto.NetMsg>>(config);

        // 生成NetMsg.cs
        var sb = new StringBuilder();
        sb.Append(SheetEditor.LineText("/**"));
        sb.Append(SheetEditor.LineText(" * Tool generation, do not modify!!!"));
        sb.Append(SheetEditor.LineText(" */\n"));
        sb.Append(SheetEditor.LineText("using System;\nusing Base.Debug;\nusing Base.Utils;\nusing System.Collections.Generic;\n"));
        sb.Append(SheetEditor.LineText("public class NetMsg\n{"));
        foreach (var msg in netMsg.list)
        {
            sb.Append(SheetEditor.LineText("public const int " + msg.MsgName.ToUpper() + " = " + msg.MsgId + ";", 1));
        }
        sb.Append(SheetEditor.LineText("//=============================================================================", 1));
        sb.Append(SheetEditor.LineText("private static Dictionary<int, Type> MsgIdTypeDict;\n", 1));
        sb.Append(SheetEditor.LineText("public static void Init()", 1));
        sb.Append(SheetEditor.LineText("{", 1));
        sb.Append(SheetEditor.LineText("MsgIdTypeDict = new Dictionary<int, Type>();", 2));
        foreach (var msg in netMsg.list)
        {
            var msgName = msg.MsgName.ToUpper();
            var str = "MsgIdTypeDict.Add({0}, typeof({1}));";
            sb.Append(SheetEditor.LineText(string.Format(str, msgName, msg.Response), 2));
        }
        sb.Append(SheetEditor.LineText("}\n", 1));
        sb.Append(SheetEditor.LineText("public static Type GetTypeByMsgId(int msgId)", 1));
        sb.Append(SheetEditor.LineText("{", 1));
        sb.Append(SheetEditor.LineText("if (MsgIdTypeDict == null) Init();", 2));
        sb.Append(SheetEditor.LineText("if (MsgIdTypeDict.ContainsKey(msgId))", 2));
        sb.Append(SheetEditor.LineText("{", 2));
        sb.Append(SheetEditor.LineText("return MsgIdTypeDict[msgId];", 3));
        sb.Append(SheetEditor.LineText("}", 2));
        sb.Append(SheetEditor.LineText("Debugger.LogError(StringUtil.Concat(\"Not Find Msg Type! Error MsgId: \", msgId));", 2));
        sb.Append(SheetEditor.LineText("return null;", 2));
        sb.Append(SheetEditor.LineText("}", 1));
        // 写入
        sb.Append(SheetEditor.LineText("}"));
        Base.Utils.FileUtil.WriteAllText(OUTNETMSGPATH, sb.ToString());
        Debugger.Log("Proto ExportNetMsg Done!");
    }

    public static void docmd(string dir)
    {
        var protoDir = new DirectoryInfo(PROTOPATH);
        var files = protoDir.GetFiles();

        foreach (var file in files)
        {
            UnityEngine.Debug.Log(file.Name);
            //string showname = $"protogen proto\\{file.Name} --csharp_out=\"{outputpath}\"";
            string str1 = $"{dir}\\{file.Name} --csharp_out=\"{outputpath}\"";
            //UnityEngine.Debug.Log(showname);

            CallProcess($"E:\\clr_text\\git\\Server\\protogen.exe", str1);

        }

      
    }

    public static bool CallProcess(string processName, string param)
    {
        try
        {
            ProcessStartInfo processInfo = new ProcessStartInfo
            {
                CreateNoWindow = false,
                UseShellExecute = false,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                FileName = processName,
                Arguments = param,
            };
            Process p = Process.Start(processInfo);
            p.WaitForExit();


            string output = p.StandardOutput.ReadToEnd();
            if (!string.IsNullOrEmpty(output))
                UnityEngine.Debug.Log(output);


            string error = p.StandardError.ReadToEnd();
            if (!string.IsNullOrEmpty(error))
                UnityEngine.Debug.LogError(processName + "  " + param + "  error: " + error);

        }
        catch (Exception e)
        {
            UnityEngine.Debug.Log(e.Message);
            return false;
        }

        return true;
    }


}
